/*******************************************************************************
 * Copyright (c) 2007, Geophysical Center RAS
 * Sergey Berezin, Dmitry Voitsekhovskiy
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms,
 * with or without modification, are permitted provided
 * that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * - Neither the name of the Geophysical Center RAS nor the names
 * of its contributors may be used to endorse or promote products
 * derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ******************************************************************************/
using System;
using System.Diagnostics;
using System.Drawing;

namespace VisualEsse.DataEngine.Types
{

	public interface IPalette {
		Color GetColor(double t);
	}

	public class LinearPalette : IPalette {

		protected double[] points;
		protected Color[] colors;

		public LinearPalette(int size) {
			Debug.Assert(size > 1);
			points = new double[size];
			colors = new Color[size];
			for(int i = 0;i<size;i++)
				points[i] = i/(double)(size - 1);
		}

		public Color GetColor(double t) {
			if(t <= 0)
				return colors[0];
			else if(t >= 1)
				return colors[colors.Length - 1];
            else if(double.IsNaN(t))
                return colors[0];
			else {
				int i = 0;
				while(points[i] < t)
					i++;
				Debug.Assert(0 < i && i < colors.Length);
				double alpha = (points[i] - t)/(points[i] - points[i-1]);
				Debug.Assert(0 <= alpha && alpha <= 1);
				Color c0 = colors[i-1];
				Color c1 = colors[i];
                return Color.FromArgb(
                    (int)(c0.A * alpha + c1.A * (1 - alpha)),
                    (int)(c0.R * alpha + c1.R * (1 - alpha)),
                    (int)(c0.G * alpha + c1.G * (1 - alpha)),
                    (int)(c0.B * alpha + c1.B * (1 - alpha)));
			}
		}

		static public LinearPalette BlackAndWhitePalette {
			get {
				LinearPalette result = new LinearPalette(2);
				result.colors[1] = Color.White;
				result.colors[0] = Color.Black;
				return result;
			}
		}

        static public LinearPalette TransparentBlackAndWhitePalette
        {
            get
            {
                LinearPalette result = new LinearPalette(4);
                result.colors[0] = Color.FromArgb(0, 0, 0, 0);
                result.colors[1] = Color.FromArgb(64, 128, 128, 128);
                result.colors[2] = Color.FromArgb(192, 192, 192, 192);
                result.colors[3] = Color.FromArgb(255, 255, 255, 255);
                
                return result;
            }
        }

		static public LinearPalette RedGreenBluePalette {
			get {
				LinearPalette result = new LinearPalette(3);
				result.colors[0] = Color.FromArgb(0,0,255);
				result.colors[1] = Color.FromArgb(0,255,0);
				result.colors[2] = Color.FromArgb(255,0,0);
				return result;
			}
		}

        public double[] Points
        {
            get
            {
                return points;
            }
        }

        public Color[] Colors
        {
            get
            {
                return colors;
            }
        }
	}
}